#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2025/11/2 16:05
# @Author  : summer
# @Email   : 610658552@qq.com
# @File    : view_wechat.py
# @Software: PyCharm
# @Desc    : 微信公众号模板消息发送视图
import logging
from rest_framework.exceptions import ValidationError
from rest_framework.generics import GenericAPIView

from common.utils.rsp import success_response
from wechat.models import WechatTemplate, WechatOpenid, WechatLog
from push.sers.ser_wechat import WechatTemplateSendSerializer
from wechat.utils.util_wx import WechatOfficialAccountMsg

# 初始化业务日志器（与短信发送保持一致）
logger = logging.getLogger('business')


class WechatSendView(GenericAPIView):
    """
    微信公众号模板消息发送接口：
    - POST: 通过模板ID发送公众号模板消息，自动记录发送日志
    - 支持通过手机号查openid，或直接传openid
    """
    serializer_class = WechatTemplateSendSerializer

    def post(self, request, pk):
        try:
            client_ip = request.META.get('REMOTE_ADDR', '未知IP')
            # 2. 序列化器参数校验（依赖WechatTemplateSendSerializer）
            serializer = self.get_serializer(data=request.data)
            serializer.is_valid(raise_exception=True)
            validated_data = serializer.validated_data
            logger.debug(f"微信公众发送参数校验通过 | 校验后数据: {validated_data}")

            # 3. 提取参数（从校验后的数据获取，确保格式合法）
            send_data = validated_data["send_data"]  # 模板变量（已校验格式）
            url = validated_data.get("url")  # 可选跳转链接
            miniprogram = validated_data.get("miniprogram", {})  # 可选小程序配置
            phone = validated_data.get("phone","")  # 手机号（可能为空，优先用openid）
            openid = validated_data.get("openid", "")  # openid（可能为空）


            try:
                wechat_template = WechatTemplate.objects.get(
                    pk=pk,
                    is_delete=0,  # 仅查询未删除的模板
                    pt_flag=0,    # 排除压测数据
                    is_active=1   # 仅查询启用的模板
                )
            except WechatTemplate.DoesNotExist:
                err_msg = f"微信公众号模板不存在或已禁用（ID: {pk}）"
                raise ValidationError({"error": err_msg})

            # 5. 处理openid：若没传openid，通过手机号查WechatOpenid表
            if not openid and phone:
                try:
                    wechat_openid = WechatOpenid.objects.get(
                        phone=phone,
                        is_delete=0,
                        is_active=1
                    )
                    openid = wechat_openid.openid
                except WechatOpenid.DoesNotExist:
                    err_msg = f"未查询到手机号「{phone}」关联的openid（需先在WechatOpenid表配置）"
                    raise ValidationError({"error": err_msg})

            # 6. 初始化微信公众号客户端，发送模板消息
            try:
                # 实例化客户端（用模板配置的AppID和AppSecret）
                # print(f'app_id={wechat_template.wx_app_id}')
                # print(f'app_secret={wechat_template.wx_app_secret}')
                # print(f'send_data={send_data}')
                # print(f'openid={openid}')
                # print(f'template_id={wechat_template.template_id}')

                wechat_client = WechatOfficialAccountMsg(
                    app_id=wechat_template.wx_app_id,
                    app_secret=wechat_template.wx_app_secret
                )

                send_result = wechat_client.send_template_msg(
                    openid=openid,
                    template_id=wechat_template.template_id,
                    data=send_data,
                    url=url,
                    miniprogram=miniprogram
                )
                print(f'send_result={send_result}')
            except Exception as e:
                err_msg = f"微信公众号消息发送失败：{str(e)}"
                raise ValidationError({"error": err_msg})

            # 7. 解析发送结果，记录WechatLog日志
            ret_success = "msgid" in send_result  # 有msgid表示发送成功
            msgid = send_result.get("msgid", "无")
            request_id = send_result.get("request_id", "无")  # 微信接口请求ID（用于排查问题）
            # 构造日志内容（成功显式msgid，失败显式错误原因）
            MAX_WECHAT_CONTENT_LENGTH = 1024  # 和 WechatLog 模型的 content 字段 max_length 一致

            # 2. 构造日志内容后，立即截断
            wechat_content = (
                f"请求IP：{client_ip}"
                f"模板ID：{wechat_template.template_id}，openid：{openid}，"
                f"模板变量：{send_data}，msgid：{msgid}，请求ID：{request_id}"
                if ret_success else f"发送失败：{send_result.get('errmsg', '未知错误')}，请求ID：{request_id}"
            )
            # 关键：超过最大长度就截断，预留 15 字符放省略号（避免截断到一半）
            if len(wechat_content) > MAX_WECHAT_CONTENT_LENGTH:
                wechat_content = wechat_content[:MAX_WECHAT_CONTENT_LENGTH - 20] + "...（内容超长已截断）"

            # 3. 再写入日志（此时内容已确保不超长）
            WechatLog.objects.create(
                phone=phone,
                openid=openid,
                template_id=wechat_template.template_id,
                content=wechat_content,  # 截断后安全入库
                is_send=1 if ret_success else 0
            )
            # 8. 返回成功响应（携带msgid和request_id，便于追溯）
            return success_response(
                success=ret_success,
                message=f"微信公众号模板消息发送{'成功' if ret_success else '失败'}",
                data={
                    "msgid": msgid,
                    "request_id": request_id,
                    "openid": openid,
                    "template_id": wechat_template.template_id
                }
            )

        # 9. 捕获未知异常，记录日志并抛出
        except Exception as e:
            err_msg = f"微信公众号模板消息发送流程异常：{str(e)}"
            logger.error(err_msg, exc_info=True)
            raise  # 交给DRF统一处理，返回500错误